package com.gs.synedocket.fragment.base;

import android.Manifest;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.gs.synedocket.R;
import com.gs.synedocket.activity.ImagePreviewActivity;
import com.gs.synedocket.adapter.PhotoAdapter;
import com.gs.synedocket.apiresult.ApiResultData;
import com.gs.synedocket.constant.AllConstants;
import com.gs.synedocket.constant.EventCode;
import com.gs.synedocket.constant.HandleCode;
import com.gs.synedocket.control.AutoTexturePreviewView;
import com.gs.synedocket.control.TitleView;
import com.gs.synedocket.db.bean.Event;
import com.gs.synedocket.db.dao.LogUtil;
import com.gs.synedocket.db.dto.DocketAccRepDto;
import com.gs.synedocket.db.entity.DocketPhoto;
import com.gs.synedocket.db.sqlite.DBApi;
import com.gs.synedocket.dialog.ComboPicDialog;
import com.gs.synedocket.dialog.CommDialogUtils;
import com.gs.synedocket.dialog.DialogUtil;
import com.gs.synedocket.dialog.SignDialog;
import com.gs.synedocket.dialog.TermDialog;
import com.gs.synedocket.dialog.ToastDialogUtils;
import com.gs.synedocket.presenter.BasePresenter;
import com.gs.synedocket.service.GpsService;
import com.gs.synedocket.util.CameraUtil;
import com.gs.synedocket.util.DateUtil;
import com.gs.synedocket.util.DensityUtil;
import com.gs.synedocket.util.DocketUtil;
import com.gs.synedocket.util.FileUtils;
import com.gs.synedocket.util.OKHttpUtil;
import com.gs.synedocket.util.PermissionUtil;
import com.gs.synedocket.util.PhotoUtil;
import com.gs.synedocket.util.StringUtil;

import org.greenrobot.eventbus.EventBus;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

public abstract class BaseSignFragment<V, T extends BasePresenter<V>> extends Fragment {
    protected Context context;
    private View view;
    protected T mPresenter;
    protected TextView tvAgree, tvTime;
    protected String mSignPhoto, mTakePhoto;
    protected SignDialog signDialog;
    protected final String format = "HH:mm，dd MMM yyyy";
    protected LinearLayout llReport;
    protected CheckBox cbSite, cbAccident, cbTraffic;
    protected Calendar calendar;
    protected EditText etDetail;
    protected List<DocketPhoto> listReport;
    protected PhotoAdapter adapterReport;
    protected Button btnSubmit, btnUnSign;
    protected DocketAccRepDto mBean;
    protected boolean isPhoto, isTakePhoto;
    protected AutoTexturePreviewView previewView;
    protected CameraUtil cameraUtil;
    protected TermDialog termDialog;
    protected Handler handler = new Handler(Looper.getMainLooper()) {
        @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case HandleCode.MSG_PHOTO:
                    isTakePhoto = true;
                    takePhoto((String) msg.obj);
                    break;
                case HandleCode.MSG_CAMERA_NOT:
                case HandleCode.MSG_CAPTURE_ERROR:
                    captureError();
                    PermissionUtil.addPermission(getActivity(), new String[]{
                            Manifest.permission.CAMERA}, AllConstants.CAMERA_PREVIEW);
                    openCamera();
                    break;
            }
        }
    };

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        view = inflater.inflate(getLayoutId(), container, false);
        context = getActivity();
        mPresenter = createPresenter();
        if (mPresenter != null) {
            mPresenter.attachView((V) this);
        }
        tvAgree = fd(R.id.tv_agree);
        if (termDialog == null) {
            termDialog = new TermDialog(context);
        }
        StringUtil.setClick(context, tvAgree, termDialog);
        btnUnSign = fd(R.id.btn_unsigned);
        MyOnClickListener onClickListener = new MyOnClickListener();
        fd(R.id.btn_signature).setOnClickListener(onClickListener);
        // 事件报告
        TitleView viewReport = fd(R.id.view_report);
        if (viewReport != null) {
            llReport = fd(R.id.ll_report);
            viewReport.setContent(llReport);
            cbSite = fd(R.id.cb_site);
            cbAccident = fd(R.id.cb_accident);
            cbTraffic = fd(R.id.cb_traffic);
            tvTime = fd(R.id.tv_time);
            tvTime.setText(DateUtil.DateTimeToStr(new Date(), format));
            calendar = Calendar.getInstance();
            etDetail = fd(R.id.et_detail);
            listReport = new ArrayList<>();
            adapterReport = new PhotoAdapter(context, listReport, R.layout.rvitem_photo);
            adapterReport.setOnItemChildrenClickListener((v, position) -> {
                if (v.getId() == R.id.iv_delete) {
                    deleteReportPhoto(position);
                } else {
                    Intent intent = new Intent();
                    intent.setClass(context, ImagePreviewActivity.class);
                    ArrayList<String> listPhotos = new ArrayList<>();
                    for (int i = 0; i < listReport.size(); i++) {
                        String photo = listReport.get(i).getPhoto();
                        listPhotos.add((StringUtil.isLocalPhoto(photo) ? "" : StringUtil.isNetPhoto(photo) ? "" : OKHttpUtil.IMG_URL) + photo);
                    }
                    intent.putExtra(AllConstants.WHAT, listPhotos);
                    intent.putExtra(AllConstants.ID, position);
                    startActivity(intent);
                }
            });
            RecyclerView rvReportPhoto = fd(R.id.rv_report_photo);
            rvReportPhoto.setLayoutManager(new GridLayoutManager(context, 3));
            rvReportPhoto.setAdapter(adapterReport);
            fd(R.id.iv_add_report_photo).setOnClickListener(onClickListener);
            fd(R.id.tv_change).setOnClickListener(onClickListener);
            btnSubmit = fd(R.id.btn_submit);
            btnSubmit.setOnClickListener(onClickListener);
            initReport();
        }
        // 预览相机
        previewView = fd(R.id.textureView);
        initView();
        initData();
        return view;
    }

    /**
     * 設置事件報告數據
     */
    protected void initReport() {
        if (DocketUtil.getInstance().getAccRep() != null) {
            DocketAccRepDto accRep = DocketUtil.getInstance().getAccRep();
            if (accRep.getAccRepType() != null) {
                switch (accRep.getAccRepType()) {
                    case 1:
                        cbSite.setChecked(true);
                        break;
                    case 12:
                        cbSite.setChecked(true);
                        cbAccident.setChecked(true);
                        break;
                    case 6:
                        cbSite.setChecked(true);
                        cbAccident.setChecked(true);
                        cbTraffic.setChecked(true);
                        break;
                    case 13:
                        cbSite.setChecked(true);
                        cbTraffic.setChecked(true);
                        break;
                    case 2:
                        cbAccident.setChecked(true);
                        break;
                    case 23:
                        cbAccident.setChecked(true);
                        cbTraffic.setChecked(true);
                        break;
                    case 3:
                        cbTraffic.setChecked(true);
                        break;
                }
            }
            if (accRep.getAccRepAt() != null) {
                calendar.setTime(accRep.getAccRepAt());
                tvTime.setText(DateUtil.DateTimeToStr(accRep.getAccRepAt(), format));
            }
            etDetail.setText(accRep.getDetail() == null ? "" : accRep.getDetail());
            List<DocketPhoto> photos = accRep.getDocketAccRepPhotos();
            if (photos != null && !photos.isEmpty()) {
                for (DocketPhoto bean : photos) {
                    String photo = bean.getPhoto();
                    listReport.add(new DocketPhoto((StringUtil.isLocalPhoto(photo) ? "" : OKHttpUtil.IMG_URL) + photo));
                }
                adapterReport.notifyDataSetChanged();
                DensityUtil.setNewHeight(llReport, DensityUtil.displayViewHeight(llReport));
            }
        }
    }

    /**
     * 刪除事件報告圖片
     *
     * @param position
     */
    protected void deleteReportPhoto(int position) {
        adapterReport.delete(position);
        int size = listReport.size();
        if (size % 3 == 0) {
            DensityUtil.setNewHeight(llReport, llReport.getHeight() - DensityUtil.dp2px(100));
        }
    }

    protected abstract int getLayoutId();

    protected abstract T createPresenter();

    protected abstract void initView();

    protected abstract void initData();

    /**
     * 上传签名及内容
     */
    protected abstract void confirm();

    /**
     * 上传事件报告
     */
    protected abstract void submitReport();

    /**
     * 上传事件报告里面拍照/图库的图片
     *
     * @param url
     */
    protected abstract void uploadReportPhoto(String url);

    /**
     * 上传签名时拍照的图片
     *
     * @param url
     */
    protected abstract void takePhoto(String url);

    /**
     * 签名时拍照异常返回
     */
    protected abstract void captureError();

    class MyOnClickListener implements View.OnClickListener {

        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.btn_signature:
                    if (signDialog == null) {
                        signDialog = new SignDialog(context, signPhoto -> {
                            mSignPhoto = signPhoto;
                            confirm();
                        });
                    }
                    signDialog.show();
                    break;
                // 提交事件報告
                case R.id.btn_submit:
                    submitReport();
                    break;
                // 事件報告修改時間
                case R.id.tv_change:
                    DateUtil.showDateSelector(context, R.string.p_sel, v, calendar, "yyyyMMddHHmm", date -> {
                        calendar.setTime(date);
                        tvTime.setText(DateUtil.DateTimeToStr(date, format));
                    });
                    break;
                // 添加事件報告圖片
                case R.id.iv_add_report_photo:
                    isPhoto = true;
                    CommDialogUtils.showComboPicDialog(getActivity(), "");
                    break;
            }
        }
    }

    protected <I extends View> I fd(int id) {
        return view.findViewById(id);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (mPresenter != null) {
            mPresenter.detachView();
        }
        if (EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().unregister(this);
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        DialogUtil.getInstance().dialogDestroy(new Dialog[]{signDialog, termDialog});
    }

    /**
     * 初始化簽名
     */
    protected void clear() {
        mSignPhoto = null;
        mTakePhoto = null;
    }

    /**
     * 初始化事件報告
     */
    protected void clearReport() {
        cbSite.setChecked(false);
        cbAccident.setChecked(false);
        cbTraffic.setChecked(false);
        Date date = new Date();
        tvTime.setText(DateUtil.DateTimeToStr(date, format));
        calendar.setTime(date);
        int sizeReport = listReport.size();
        sizeReport = sizeReport % 3 == 0 ? sizeReport / 3 : (sizeReport / 3) + 1;
        DensityUtil.setNewHeight(llReport, llReport.getHeight() - (DensityUtil.dp2px(100) * sizeReport));
        adapterReport.clear();
        etDetail.setText("");
    }

    /**
     * 添加事件報告成功
     *
     * @param apiResult
     */
    protected void addReportSuccess(ApiResultData<String> apiResult) {
        ToastDialogUtils.getInstance().showInfoMessage(context, apiResult.getMessage());
        if (apiResult.getStatus() != 2000) {
            return;
        }
        DocketUtil.getInstance().setAccRep(mBean);
        DBApi.getInstance().updateDocketUpload(mBean.getDocketId(), 0);
        DBApi.getInstance().insertNewAccRep(mBean);
        LogUtil.getInstance().insertOrReplaceData(DocketUtil.getInstance().getDocketNo() + "-添加事件報告成功");
    }

    /**
     * 获取事件报告dto
     *
     * @return
     */
    protected DocketAccRepDto createDto() {
        DocketAccRepDto bean = new DocketAccRepDto();
        if (!listReport.isEmpty()) {
            bean.setDocketAccRepPhotos(resetPhoto(listReport));
        }
        bean.setDocketId(DocketUtil.getInstance().getDocketId());
        bean.setAccRepType(getAccRepType());
        bean.setAccRepAt(getAccRepAt());
        bean.setDetail(getDetail());
        bean.setGps(GpsService.getGps());
        bean.setGpsLoc(GpsService.getGpsLoc());
        mBean = bean;
        return bean;
    }

    private Integer getAccRepType() {
        Integer type = null;
        if (cbSite.isChecked()) {
            type = 1;
            if (cbAccident.isChecked()) {
                type = 12;
                if (cbTraffic.isChecked()) {
                    type = 6;
                }
            } else if (cbTraffic.isChecked()) {
                type = 13;
            }
        } else {
            if (cbAccident.isChecked()) {
                type = 2;
                if (cbTraffic.isChecked()) {
                    type = 23;
                }
            } else if (cbTraffic.isChecked()) {
                type = 3;
            }
        }
        return type;
    }

    /**
     * 去除图片的前缀
     *
     * @param list
     * @return
     */
    private List<DocketPhoto> resetPhoto(List<DocketPhoto> list) {
        List<DocketPhoto> newList = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            String photo = list.get(i).getPhoto();
            newList.add(list.get(i));
            if (photo.startsWith(OKHttpUtil.IMG_URL)) {
                newList.get(i).setPhoto(photo.substring(OKHttpUtil.IMG_URL.length()));
            }
        }
        return newList;
    }

    private Date getAccRepAt() {
        return calendar.getTime();
    }

    private String getDetail() {
        return etDetail.getText().toString();
    }

    public void withoutSignSuccess() {
        LogUtil.getInstance().insertOrReplaceData(DocketUtil.getInstance().getDocketNo() + "-未能完成簽名");
        DBApi.getInstance().updateDocketState(DocketUtil.getInstance().getDocketId(), 5);
        DocketUtil.getInstance().setDriverState(5);
        EventBus.getDefault().post(new Event(EventCode.EVENT_DONE_COMPLETE));
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    public void onHiddenChanged(boolean hidden) {
        super.onHiddenChanged(hidden);
        if (hidden) {
            cameraUtil.closeCamera();
            if (signDialog != null) {
                signDialog.viewSign.clear();
            }
        } else {
            openCamera();
        }
    }

    /**
     * 打开签名时拍照的摄像机
     */
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private void openCamera() {
        cameraUtil = new CameraUtil(getActivity(), previewView, previewView.getTextureView(), handler);
        cameraUtil.open();
    }

    /**
     * 拍照/图库的图片返回
     *
     * @param requestCode
     * @param resultCode
     * @param data
     */
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    protected void photoResult(int requestCode, int resultCode, Intent data) {
        if (resultCode != 0) {
            String url = null;
            if (requestCode == AllConstants.PIC_CAMERA) {
                openCamera();
                url = PhotoUtil.getInstance().handlePhoto(context);
            } else if (requestCode == AllConstants.PIC_GALLERY && data != null) {
                if (data.getData() != null) {
                    url = FileUtils.getFilePathByUri(context, data.getData());
                }
            }
            if (!TextUtils.isEmpty(url)) {
                adapterReport.add(new DocketPhoto(url));
                int size = listReport.size();
                if (size % 3 == 1) {
                    DensityUtil.setNewHeight(llReport, llReport.getHeight() + DensityUtil.dp2px(110));
                }
                uploadReportPhoto(url);
            }
        }
    }

    /**
     * 拍照/圖庫權限返回
     *
     * @param requestCode
     * @param grantResults
     */
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    protected void photoPermissionsResult(int requestCode, int[] grantResults) {
        if (PermissionUtil.requestPermission(grantResults)) {
            // 申请相机权限后返回(預覽)
            if (requestCode == AllConstants.CAMERA_PREVIEW) {
                openCamera();
            }
            // 申请相机权限后返回
            else if (requestCode == ComboPicDialog.PIC_CAMERA) {
                PhotoUtil.getInstance().toCamera(getActivity());
            }
            // 申请读取图库权限后返回
            else if (requestCode == ComboPicDialog.PIC_GALLERY) {
                PhotoUtil.getInstance().toGallery(getActivity());
            }
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    public void onResume() {
        super.onResume();
        if (!isHidden()) {
            openCamera();
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    public void onPause() {
        super.onPause();
        if (!isHidden()) {
            cameraUtil.closeCamera();
        }
    }
}
